package com.xbongbong.saas.help;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.xbongbong.i18n.util.I18nMessageUtil;
import com.xbongbong.paas.constant.MessageConstant;
import com.xbongbong.paas.constant.PaasConstant;
import com.xbongbong.paas.domain.entity.PaasFormExplainEntity;
import com.xbongbong.paas.domain.entity.PaasStageEntity;
import com.xbongbong.paas.domain.entity.StageLogEntity;
import com.xbongbong.paas.domain.entity.StageProcessEntity;
import com.xbongbong.paas.enums.DelEnum;
import com.xbongbong.paas.enums.EnableEnum;
import com.xbongbong.paas.enums.PlatFormEnum;
import com.xbongbong.paas.enums.StageTypeEnum;
import com.xbongbong.paas.field.FieldAttrEntity;
import com.xbongbong.paas.help.StageLogHelp;
import com.xbongbong.paas.model.PaasFormExplainModel;
import com.xbongbong.paas.model.StageProcessModel;
import com.xbongbong.paas.pojo.dto.FormDataUpdateDTO;
import com.xbongbong.paas.service.workflow.WorkflowDataService;
import com.xbongbong.paas.toolbox.exception.XbbException;
import com.xbongbong.paas.toolbox.util.CloneUtil;
import com.xbongbong.paas.toolbox.util.CollectionsUtil;
import com.xbongbong.paas.toolbox.util.StringUtil;
import com.xbongbong.paas.toolbox.wrap.UserVO;
import com.xbongbong.paas.util.ExplainUtil;
import com.xbongbong.pro.businesstage.pojo.dto.ChangeStageDTO;
import com.xbongbong.pro.businesstage.pojo.vo.ChangeStageVO;
import com.xbongbong.pro.constant.BusinessConstant;
import com.xbongbong.pro.enums.SaasMarkEnum;
import com.xbongbong.pro.enums.errorcodes.SystemErrorCodeEnum;
import com.xbongbong.pro.opportunity.pojo.JudgeSaleStageSuccessPojo;
import com.xbongbong.pro.opportunity.pojo.JudgeStageChangedPojo;
import com.xbongbong.pro.opportunity.pojo.StageLogSavePojo;
import com.xbongbong.saas.constant.BasicConstant;
import com.xbongbong.saas.constant.ParameterConstant;
import com.xbongbong.saas.domain.entity.OpportunityProductEntity;
import com.xbongbong.saas.domain.entity.OpportunityUserEntity;
import com.xbongbong.saas.domain.entity.SaleStageEntity;
import com.xbongbong.saas.domain.entity.UserTeamEntity;
import com.xbongbong.saas.domain.entity.ext.OpportunityEntityExt;
import com.xbongbong.saas.enums.XbbRefTypeEnum;
import com.xbongbong.saas.enums.business.ContractEnum;
import com.xbongbong.saas.enums.business.SalesOpportunityEnum;
import com.xbongbong.saas.enums.product.OpportunityProductEnum;
import com.xbongbong.saas.model.OpportunityModel;
import com.xbongbong.saas.model.OpportunityProductModel;
import com.xbongbong.saas.model.OpportunityStageLogModel;
import com.xbongbong.saas.model.OpportunityUserModel;
import com.xbongbong.saas.model.SaleStageModel;
import com.xbongbong.saas.toolbox.help.FastJsonHelper;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;

import static com.xbongbong.saas.constant.BasicConstant.MAIN_USER;

/**
 *
 * @author 魏荣杰
 *
 */
@Component
@Slf4j
public class OpportunityStageLogHelp {

    @Resource
    private SaleStageModel saleStageModel;
    @Resource
    private OpportunityModel opportunityModel;
    @Resource
    private OpportunityProductModel opportunityProductModel;
    @Resource
    private OpportunityUserModel opportunityUserModel;
    @Resource
    private WorkflowDataService workflowDataService;
    @Resource
    private StageProcessModel stageProcessModel;
    @Resource
    private OpportunityStageLogModel opportunityStageLogModel;
    @Resource
    private StageLogHelp stageLogHelp;
    @Resource
    private PaasFormExplainModel paasFormExplainModel;

    /**
     * @Description: 判断合同中关联机会字段是否启用
     * @param formId
     * @param corpid
     * @Author cml
     * @CreateTime 2023/3/6 15:55
     */
    public boolean getIsLinkOpportunity(Long formId, String corpid) throws XbbException {
        boolean isLinkOpportunity = false;
        if (Objects.isNull(formId) || StringUtil.isEmpty(corpid)) {
            return isLinkOpportunity;
        }
        PaasFormExplainEntity paasFormExplainEntity = paasFormExplainModel.getByFormId(formId, corpid);
        if (Objects.isNull(paasFormExplainEntity) || StringUtil.isEmpty(paasFormExplainEntity.getExplains())) {
            return isLinkOpportunity;
        }
        Map<String, FieldAttrEntity> explainMap = ExplainUtil.getExplainMap(paasFormExplainEntity.getExplains(), null);
        if (explainMap.containsKey(ContractEnum.LINK_OPPORTUNITY.getAttr())) {
            FieldAttrEntity fieldAttrEntity = explainMap.get(ContractEnum.LINK_OPPORTUNITY.getAttr());
            if (Objects.equals(fieldAttrEntity.getIsOpen(), BasicConstant.ONE)) {
                isLinkOpportunity = true;
            }
        }
        return isLinkOpportunity;
    }

    /**
     * 新建合同或者合同审批通过后将机会状态改为赢单
     *
     * @param changeStageDTO
     * @return
     * @throws XbbException
     */
    public ChangeStageVO changeStage(ChangeStageDTO changeStageDTO) throws XbbException {
        ChangeStageVO changeStageVO = new ChangeStageVO();
        changeStageVO.setMsg(I18nMessageUtil.getMessage(MessageConstant.FORM_ADD_RETURN_MSG));
        changeStageVO.setCode(PaasConstant.FORM_ADD_RETURN_CODE);
        changeStageVO.setFormDataId(changeStageDTO.getDataId());

        String corpid = changeStageDTO.getCorpid();
        Long opportunityId = changeStageDTO.getDataId();
        UserVO userVO = changeStageDTO.getLoginUser();

        OpportunityEntityExt opportunityEntity = changeStageDTO.getOpportunity();
        if (Objects.isNull(opportunityEntity)) {
            opportunityEntity = opportunityModel.getByKey(opportunityId, corpid);
        }
        if(Objects.isNull(opportunityEntity) || Objects.equals(opportunityEntity.getDel(), 1)) {
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100404);
        }

        PaasStageEntity targetStage = changeStageDTO.getTargetStage();
        if (Objects.isNull(targetStage)) {
            targetStage = saleStageModel.getByCode(corpid, opportunityEntity.getFormId(), changeStageDTO.getNextCode());
        }

        JSONObject newData = (JSONObject) CloneUtil.deepClone(opportunityEntity.getData());
        newData.remove(SalesOpportunityEnum.PRODUCTS.getAttr());

        if (Objects.nonNull(targetStage)) {
            newData.put(SalesOpportunityEnum.SALE_STAGE.getAttr(), targetStage.getCode());
            newData.put(SalesOpportunityEnum.STAGE_ID.getAttr(), targetStage.getId());
            newData.put(SalesOpportunityEnum.STAGE_PROCESS_ID.getAttr(), targetStage.getStageProcessId());
            newData.put(SalesOpportunityEnum.STAGE_RATIO.getAttr(), targetStage.getIntoProportion());
        } else {
            newData.remove(SalesOpportunityEnum.SALE_STAGE.getAttr());
            newData.remove(SalesOpportunityEnum.STAGE_ID.getAttr());
            newData.remove(SalesOpportunityEnum.STAGE_PROCESS_ID.getAttr());
            newData.remove(SalesOpportunityEnum.STAGE_RATIO.getAttr());
        }

        Map<String, Object> map = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        map.put(ParameterConstant.CORPID, corpid);
        map.put(ParameterConstant.DEL, DelEnum.NORMAL.getDel());
        map.put("opportunityId", opportunityEntity.getId());
        List<OpportunityUserEntity> opportunityUserEntities = opportunityUserModel.findEntitys(map);
        List<UserTeamEntity> mainUserTeamList = new ArrayList<>();
        List<UserTeamEntity> copUserTeamList = new ArrayList<>();
        opportunityUserEntities.forEach((userTeamEntity -> {
            if (Objects.equals(userTeamEntity.getIsMain(), MAIN_USER)) {
                mainUserTeamList.add(userTeamEntity);
            } else {
                copUserTeamList.add(userTeamEntity);
            }
        }));
        // 负责人和协同人
        if (CollectionsUtil.isNotEmpty(mainUserTeamList)) {
            List<String> mainIdList = new ArrayList<>();
            for (UserTeamEntity userTeamEntity : mainUserTeamList) {
                mainIdList.add(userTeamEntity.getUserId());
            }
            newData.put(SalesOpportunityEnum.OWNER_ID.getAttr(), mainIdList);
        }
        if (CollectionsUtil.isNotEmpty(copUserTeamList)) {
            List<String> coIdList = new ArrayList<>();
            for (UserTeamEntity userTeamEntity : copUserTeamList) {
                coIdList.add(userTeamEntity.getUserId());
            }
            newData.put(SalesOpportunityEnum.COUSER_ID.getAttr(), coIdList);
        }
        // 关联产品
        List<OpportunityProductEntity> productList = opportunityProductModel.getProductsByOppId(opportunityEntity.getId(), corpid);
        formatProductForProcess(productList, newData);

        if (Objects.nonNull(targetStage) && Objects.equals(StageTypeEnum.FAIL_STAGE.getType(), targetStage.getType())) {
            newData.put(SalesOpportunityEnum.WASTAGE.getAttr(), Objects.toString(changeStageDTO.getReasonId(), ""));
            newData.put(SalesOpportunityEnum.WASTAGE_MEMO.getAttr(), Objects.toString(changeStageDTO.getMemo(), ""));
        } else {
            newData.put(SalesOpportunityEnum.WASTAGE.getAttr(), "");
            newData.put(SalesOpportunityEnum.WASTAGE_MEMO.getAttr(), "");
        }

        FormDataUpdateDTO formDataUpdateDTO = new FormDataUpdateDTO(opportunityEntity.getFormId(), opportunityEntity.getAppId(), opportunityEntity.getMenuId(), opportunityEntity.getId(), newData, SaasMarkEnum.SAAS.getCode(), XbbRefTypeEnum.SALES_OPPORTUNITY.getCode(), XbbRefTypeEnum.SALES_OPPORTUNITY.getCode(), null, userVO, corpid, null, PlatFormEnum.INTERNAL.getValue());
        workflowDataService.update(formDataUpdateDTO);
        StageLogEntity sourceStageLog = null;
        PaasStageEntity sourceStage = changeStageDTO.getSourceStage();
        if (Objects.nonNull(sourceStage)) {
            sourceStageLog = opportunityStageLogModel.getStageLogByStageId(opportunityId, corpid, sourceStage.getId());
        }
        JudgeStageChangedPojo judgeStageChangedPojo = new JudgeStageChangedPojo(changeStageDTO.getTargetStage(), sourceStage, true, sourceStageLog);
        StageLogSavePojo stageLogSavePojo = new StageLogSavePojo(corpid, opportunityEntity.getFormId(), opportunityId, judgeStageChangedPojo);
        stageLogHelp.saveStageLog(stageLogSavePojo, SaasMarkEnum.SAAS.getCode(), XbbRefTypeEnum.SALES_OPPORTUNITY.getCode());
        return changeStageVO;
    }

    public void formatProductForProcess(List<OpportunityProductEntity> productList, JSONObject newData) {
        JSONArray jsonArray = new JSONArray();
        newData.put(SalesOpportunityEnum.PRODUCTS.getAttr(), jsonArray);
        for (OpportunityProductEntity opportunityProductEntity : productList) {
            JSONObject productObject = new JSONObject();
            if (Objects.nonNull(opportunityProductEntity.getData())) {
                productObject = opportunityProductEntity.getData();
            }
            productObject.put(BusinessConstant.PRODUCT_SUB_ID, opportunityProductEntity.getId());
            productObject.put(OpportunityProductEnum.PRODUCT.getAttr(), opportunityProductEntity.getProductId());
            productObject.put(OpportunityProductEnum.NUM.getAttr(), opportunityProductEntity.getProductNum());
            productObject.put(OpportunityProductEnum.SELLING_PRICE.getAttr(), opportunityProductEntity.getPrice());
            productObject.put(OpportunityProductEnum.DISCOUNT.getAttr(), opportunityProductEntity.getDiscount());
            productObject.put(OpportunityProductEnum.PRICE.getAttr(), opportunityProductEntity.getCost());
            productObject.put(OpportunityProductEnum.MEMO.getAttr(), opportunityProductEntity.getMemo());
            productObject.put(OpportunityProductEnum.UNIT.getAttr(), opportunityProductEntity.getProductUnit());
            jsonArray.add(productObject);
        }
    }

    /**
     * 创建或者编辑合同的时候判断是否需要将合同关联的销售机会阶段变更为成功阶段
     *
     * @param corpid
     * @param dataId
     * @return JudgeSaleStageSuccessPojo
     * @throws XbbException
     */
    public JudgeSaleStageSuccessPojo judgeSaleStageSuccessWhenContract(String corpid, Long dataId) throws XbbException {
        boolean needChangeStage = false;
        SaleStageEntity targetStage = null;
        SaleStageEntity sourceStage = null;
        OpportunityEntityExt opportunity = opportunityModel.getByKey(dataId, corpid);
        if (Objects.nonNull(opportunity)) {
            Long formId = opportunity.getFormId();
            String stageCode = FastJsonHelper.getStringFromFormData(opportunity.getData(), SalesOpportunityEnum.SALE_STAGE.getAttr());
            if (StringUtil.isEmpty(stageCode)) {
                StageProcessEntity stageProcess = stageProcessModel.getEnableStageProcess(corpid, formId);
                if (Objects.nonNull(stageProcess)) {
                    // 是否允许新建合同，阶段自动跳转此阶段
                    targetStage = saleStageModel.getFirstCreateContractSkipSuccessStage(corpid, formId, stageProcess.getId());
                    if (Objects.nonNull(targetStage) && Objects.equals(EnableEnum.OPEN.getCode(), targetStage.getAllowCreateContractSkipStage())) {
                        // 机会当前没有关联阶段
                        needChangeStage = true;
                    }
                }
            } else {
                // 获取机会当前所在阶段
                Long stageId = FastJsonHelper.getLongOrDefaultFromFormData(opportunity.getData(), SalesOpportunityEnum.STAGE_ID.getAttr(), 0L);
                SaleStageEntity saleStage = saleStageModel.getByKey(stageId, corpid);
                // 如果当前所在阶段已经是成功阶段，则不需要对阶段进行变更
                if (Objects.nonNull(saleStage) && !Objects.equals(saleStage.getType(), StageTypeEnum.SUCCESS_STAGE.getType())) {
                    // 获取流程下第一个成功阶段作为机会跳转的目标阶段
                    targetStage = saleStageModel.getFirstCreateContractSkipSuccessStage(corpid, saleStage.getFormId(), saleStage.getStageProcessId());
                    if (Objects.nonNull(targetStage) && Objects.equals(EnableEnum.OPEN.getCode(), targetStage.getAllowCreateContractSkipStage())) {
                        // 机会有关联阶段但是不是成功阶段
                        needChangeStage = true;
                        sourceStage = saleStage;
                    }
                }
            }
        }
        return new JudgeSaleStageSuccessPojo(needChangeStage, targetStage, sourceStage, opportunity);
    }
}
